home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
admin
/
linuxcon.000
/
linuxcon
/
linuxconf-1.6
/
netconf
/
rarp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-07-29
|
11KB
|
494 lines
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "netconf.h"
#include <netdb.h>
#include "../userconf/userconf.h"
#include "netconf.m"
static NETCONF_HELP_FILE help_rarp ("rarp");
static CONFIG_FILE f_net_rarp (PROC_NET_RARP
,help_rarp
,CONFIGF_OPTIONNAL|CONFIGF_PROBED);
class RARP_ENTRY: public ARRAY_OBJ{
public:
char seen; // Used to tell if one entry has been
// processed
char active; // This record has to be activated in the kernel
SSTRING ip; // IP number of host name
SSTRING hw; // Hardware address
SSTRING comment;
/*~PROTOBEG~ RARP_ENTRY */
public:
RARP_ENTRY (const char *_ip,
const char *_hw,
int _active,
const char *_comment);
RARP_ENTRY (const char *str, int noline);
RARP_ENTRY (void);
int cmp (const char *ipstr);
int edit (void);
int is_valid (int talk);
private:
int normalise (void);
public:
int set (void);
int unset (void);
/*~PROTOEND~ RARP_ENTRY */
};
/*
Constructor used to read /proc/net/rarp
*/
PUBLIC RARP_ENTRY::RARP_ENTRY(const char *str, int noline)
{
active = 1;
seen = 0;
char ipstr[100];
char mbps[100];
char ethernet[100];
char hwstr[100];
/* #Specification: rarp / proc/net/rarp / format
We assume this file has the following format
and are simply looking for 4 words.
#
ip_number 10Mbps Ethernet hw_address
#
We are validating the second and third word to make sure
*/
if (sscanf (str,"%s %s %s %s",ipstr,mbps,ethernet,hwstr)==4){
if (strcmp(mbps,"10Mbps")!=0
|| strcmp(ethernet,"Ethernet")!=0){
xconf_error (MSG_U(E_IVLDRARPFORM
,"Invalid format in file %s, line %d")
,f_net_rarp.getpath(),noline);
}else{
ip.setfrom (ipstr);
hw.setfrom (hwstr);
}
}
}
/*
Constructor used to read configuration.
*/
PUBLIC RARP_ENTRY::RARP_ENTRY(
const char *_ip,
const char *_hw,
int _active,
const char *_comment)
{
seen = 0;
ip.setfrom (_ip);
hw.setfrom (_hw);
active = (char)_active;
comment.setfrom (_comment);
normalise();
}
/*
Create an empty entry
*/
PUBLIC RARP_ENTRY::RARP_ENTRY()
{
seen = 0;
active = 1;
}
/*
Add this entry to the rarp table
*/
PUBLIC int RARP_ENTRY::set()
{
char buf[200];
sprintf (buf,"-s %s %s",ip.get(),hw.get());
return netconf_system_if ("rarp",buf);
}
/*
Compare one IP number with this entry
Return 0 if equal, != 0 if different.
*/
PUBLIC int RARP_ENTRY::cmp(const char *ipstr)
{
int ret = ip.cmp(ipstr);
if (ret != 0){
/* #Specification: rarp / entry / ip or host name
We can specify a host either by its IP number
or its host name.
*/
struct hostent *ent = gethostbyname(ip.get());
if (ent != NULL){
char str[20];
devices_ip2a (ent,str);
ret = strcmp(ipstr,str);
}
}
return ret;
}
/*
delete this entry from the rarp table
*/
PUBLIC int RARP_ENTRY::unset ()
{
char buf[200];
sprintf (buf,"-d %s",ip.get());
return netconf_system_if ("rarp",buf);
}
class RARP_ENTRIES: public ARRAY{
/*~PROTOBEG~ RARP_ENTRIES */
public:
RARP_ENTRIES (CONFIG_FILE&f);
RARP_ENTRIES (void);
void edit (void);
RARP_ENTRY *getitem (int no);
int isoneactive (void);
RARP_ENTRY *locate (const char *ipstr);
int save (void);
void update (RARP_ENTRIES¤t);
/*~PROTOEND~ RARP_ENTRIES */
};
PUBLIC RARP_ENTRY *RARP_ENTRIES::getitem (int no)
{
return (RARP_ENTRY*)ARRAY::getitem(no);
}
/*
Locate an entry using its IP number or name.
Only active entries are checked.
*/
PUBLIC RARP_ENTRY *RARP_ENTRIES::locate (const char *ipstr)
{
RARP_ENTRY *ret = NULL;
for (int i=0; i<getnb(); i++){
RARP_ENTRY *a = getitem(i);
if (a->active && a->cmp(ipstr)==0){
ret = a;
break;
}
}
return ret;
}
static char RARP[]="rarp";
static char ENTRY[]="entry";
/*
Load from /etc/conf.linuxconf
*/
PUBLIC RARP_ENTRIES::RARP_ENTRIES()
{
SSTRINGS strs;
linuxconf_getall (RARP,ENTRY,strs,0);
int nb = strs.getnb();
for (int i=0; i<nb; i++){
SSTRING *s = strs.getitem(i);
char ipstr[200],hwstr[200],acstr[200];
const char *pt = s->get();
pt = str_copyword (ipstr,pt);
pt = str_copyword (hwstr,pt);
pt = str_copyword (acstr,pt);
// The active field has been added. It defaults to "active"
int active = acstr[0] == '\0' ? 1 : atoi(acstr) != 0;
pt = str_skip(pt);
sscanf (s->get(),"%s %s",ipstr,hwstr);
add (new RARP_ENTRY (ipstr,hwstr,active,pt));
}
rstmodified();
}
/*
Update /etc/conf.linuxconf
*/
PUBLIC int RARP_ENTRIES::save()
{
int n = getnb();
linuxconf_removeall (RARP,ENTRY);
for (int i=0; i<n; i++){
RARP_ENTRY *e = getitem(i);
char buf[400];
sprintf (buf,"%s %s %d %s",e->ip.get(),e->hw.get(),e->active
,e->comment.get());
linuxconf_add (RARP,ENTRY,buf);
}
rstmodified();
return linuxconf_save();
}
/*
Load the running config.
*/
PUBLIC RARP_ENTRIES::RARP_ENTRIES(CONFIG_FILE &f)
{
FILE *fin = f.fopen ("r");
if (fin != NULL){
int noline = 1;
char buf[300];
// Skip the first line
fgets (buf,sizeof(buf)-1,fin);
while (fgets (buf,sizeof(buf)-1,fin) != NULL){
noline++;
add (new RARP_ENTRY(buf,noline));
}
fclose (fin);
}
}
PUBLIC void RARP_ENTRIES::update (RARP_ENTRIES ¤t)
{
int n = current.getnb();
int i;
for (i=0; i<n; i++){
RARP_ENTRY *cur_a = current.getitem(i);
RARP_ENTRY *a = locate (cur_a->ip.get());
if (a == NULL){
cur_a->unset();
}else{
a->seen = 1;
if (a->hw.cmp(cur_a->hw)!=0){
cur_a->unset();
a->set();
}
}
}
n = getnb();
for (i=0; i<n; i++){
RARP_ENTRY *a = getitem(i);
if (!a->seen && a->active) a->set();
}
}
/*
Validate and normalise the format of the hardware address.
Make sure there is 2 digits per byte. This helps when comparing
with the current setup as read from /proc/net/rarp.
*/
PRIVATE int RARP_ENTRY::normalise()
{
int digits[6];
memset (digits,0,sizeof(digits));
const char *pt = hw.get();
int err = 0;
int nbhex = 0;
int nbpt = 0;
while (*pt != '\0'){
char carac = *pt++;
if (carac == ':'){
if (nbhex == 0 || nbhex > 2) err = 1;
nbhex = 0;
nbpt++;
}else if (nbpt == 6){
err = 1;
}else if (isxdigit(carac)){
digits[nbpt] *= 16;
if (isalpha(carac)){
carac = toupper(carac) - 'A' + 10;
}else{
carac -= '0';
}
digits[nbpt] += carac;
nbhex++;
}else{
err = 1;
}
}
if (nbpt != 5 || nbhex == 0){
err = 1;
}else{
char formstr[6*2+5+0];
sprintf (formstr,"%02x:%02x:%02x:%02x:%02x:%02x"
,digits[0],digits[1],digits[2],digits[3],digits[4],digits[5]);
hw.setfrom (formstr);
}
return err ? -1 : 0;
}
/*
Return != 0 the entry is valid.
May operate silently or show errors
*/
PUBLIC int RARP_ENTRY::is_valid(int talk)
{
int ret = 0;
if (ip.is_empty() || hw.is_empty()){
if (talk) xconf_error (MSG_U(E_ALLFIELD,"All field must be filled"));
}else{
if (normalise()==-1){
if (talk){
xconf_error (MSG_U(E_HARDETH
,"Invalid hardware ethernet address\n"
"%s\n"
"Expect xx:xx:xx:xx:xx:xx format")
,hw.get());
}
}else{
ret = 1;
}
}
return ret;
}
/*
Edit one entry
Return -1 if the user cancel
Return 0 if the user accept the changes
Return 1 if the user wish to delete this record
*/
PUBLIC int RARP_ENTRY::edit()
{
int ret = -1;
DIALOG dia;
dia.newf_chk ("",active,MSG_U(F_RARPACTIVE,"This record is active"));
dia.newf_str (MSG_U(F_HOSTNAME,"host name or IP number"),ip);
dia.newf_str (MSG_U(F_ETHADR,"Ethernet address"),hw);
dia.newf_str (MSG_R(F_COMMENT),comment);
int nof = 0;
while (1){
MENU_STATUS code = dia.edit(MSG_U(T_ETH2IP,"Ethernet to IP translation")
,MSG_U(I_ETH2IP
,"Enter an IP number or a host name\n"
"and its ethernet 6 hexadecimal digit\n"
"address")
,help_rarp
,nof
,MENUBUT_CANCEL|MENUBUT_ACCEPT|MENUBUT_DEL);
if (code == MENU_CANCEL || code == MENU_ESCAPE){
break;
}else if (code == MENU_DEL){
ret = 1;
break;
}else if (is_valid(1)){
ret = 0;
break;
}
}
if (ret != 0) dia.restore();
return ret;
}
static int cmp_by_ip (const ARRAY_OBJ *o1, const ARRAY_OBJ *o2)
{
RARP_ENTRY *e1 = (RARP_ENTRY*)o1;
RARP_ENTRY *e2 = (RARP_ENTRY*)o2;
return e1->ip.cmp(e2->ip);
}
PUBLIC void RARP_ENTRIES::edit()
{
int choice = 0;
while (1){
DIALOG dia;
sort (cmp_by_ip);
for (int i=0; i<getnb(); i++){
RARP_ENTRY *e = getitem(i);
char buf1[30],buf2[100];
sprintf (buf1,"[%c] %s",e->active ? 'X' : ' ',e->ip.get());
sprintf (buf2,"%s %s",e->hw.get(),e->comment.get());
dia.new_menuitem (buf1,buf2);
}
dia.addwhat (MSG_U(I_ANEWENTRY,"a new entry"));
MENU_STATUS code = dia.editmenu(
MSG_U(T_RARPCONF,"RARP configuration")
,MSG_U(I_RARPCONF,"You are allowed to edit/add\n"
"RARP (Reverse Address Resolution)\n"
"which will allow other computer to get\n"
"their IP number from this server\n")
,help_rarp
,choice
,0);
if (code == MENU_ESCAPE || code == MENU_QUIT){
break;
}else if (perm_rootaccess(MSG_U(P_EDITRARP
,"to edit RARP configuration"))){
if (code == MENU_ADD){
RARP_ENTRY *e = new RARP_ENTRY;
if (e->edit () == 0){
add (e);
save();
}else{
delete e;
}
}else if (choice >= 0 && choice < getnb()){
RARP_ENTRY *e = getitem(choice);
if (code == MENU_OK){
int ok = e->edit();
if (ok >= 0){
if (ok == 1) remove_del (e);
save();
}
}
}
}
}
}
/*
Return != 0 if there is at least one record active
*/
PUBLIC int RARP_ENTRIES::isoneactive()
{
int ret = 0;
int n = getnb();
for (int i=0; i<n; i++){
RARP_ENTRY *e = getitem(i);
if (e->active){
ret = 1;
break;
}
}
return ret;
}
/*
Edit the RARP table used to program the kernel RARP table
*/
void rarp_edit()
{
RARP_ENTRIES rarps;
rarps.edit();
}
/*
Install, update the rarp table
*/
void rarp_activate ()
{
if (perm_rootaccess(MSG_U(P_UPDRARP,"to install RARP entry"))){
RARP_ENTRIES conf;
if (f_net_rarp.exist()){
RARP_ENTRIES cur (f_net_rarp);
conf.update (cur);
}else if (conf.isoneactive()){
/* #Specification: rarp / module
If /proc/net/rarp is not available, the command
"modprobe rarp" is executed to load the module.
The presence of /proc/net/rarp is checked again
to see if it has succeeded. An error message is
generated.
This is done only if some rarp entries are
configured.
*/
netconf_system_if ("modprobe","rarp");
if (f_net_rarp.exist()){
RARP_ENTRIES cur (f_net_rarp);
conf.update (cur);
}else{
xconf_error (MSG_U(E_NORARP
,"This kernel does not support RARP\n"
"I can't load the RARP table\n"
"Some machines may fail to boot because of that"));
}
}
}
}